package com.kang.service.warMap.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kang.CommonsUtils;
import com.kang.Constants;
import com.kang.bean.bot.*;
import com.kang.MsgResult;
import com.kang.mapper.CityMapper;
import com.kang.mapper.PopulationMapper;
import com.kang.mapper.WarMapMapper;
import com.kang.service.warMap.CityService;
import com.kang.vo.CityVo;
import com.kang.vo.PopulationVo;
import love.forte.simbot.api.message.containers.GroupAccountInfo;
import love.forte.simbot.api.message.events.GroupMsg;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @program: service
 * @description:
 * @author: K.faWu
 * @create: 2022-06-09 10:08
 **/
@Service
public class CityServiceImpl extends ServiceImpl<CityMapper, City> implements CityService {
    @Autowired
    private CityMapper cityMapper;
    @Autowired
    private PopulationMapper populationMapper;
    @Autowired
    private WarMapMapper warMapMapper;

    /**
     * 获取账号信息，包括资源数量
     * @param accountCode 账号
     * @param groupCode 群号
     * @return 账号信息
     */
    @Override
    public CityVo getCityInfo(String accountCode, String groupCode) {
        CityVo cityVo = cityMapper.getCityInfo(accountCode, groupCode);
        if (cityVo != null) {
            this.getProInfo(accountCode, groupCode, cityVo);
        }
        return cityVo;
    }

    public void getProInfo(String accountCode, String groupCode, CityVo cityVo){
        QueryWrapper<WarMap> queryWrapper = CommonsUtils.selectCode(accountCode, groupCode);
        List<WarMap> list = warMapMapper.selectList(queryWrapper);
        cityVo.setWarMapList(list);
        cityVo.setNum((long) list.size());
        PopulationVo porInfo = cityVo.getPorInfo();
        for (WarMap warMap : list){
            //人口上限统计
            porInfo.setMax(warMap.getProMax() + porInfo.getMax());
            //农名数量统计
            porInfo.setProNum(porInfo.getProNum() + warMap.getFarmerNum());
            //士兵数量统计
            porInfo.setSoldierNum(porInfo.getSoldierNum() + warMap.getSoldierNum());
            //士兵上限统计
            porInfo.setSoldierMax(porInfo.getSoldierMax() + warMap.getSoldierMax());
            //伐木工数量统计
            porInfo.setWoodcutterNum(porInfo.getWoodcutterNum() + warMap.getWoodNum());
            //伐木工上限
            porInfo.setWoodMax(porInfo.getWoodMax() + warMap.getWoodMax());
            //矿工数量
            porInfo.setMinerNum(porInfo.getMinerNum() + warMap.getMinerNum());
            //矿工上限
            porInfo.setMinerMax(porInfo.getMinerMax() + warMap.getMinerMax());
        }
        //当前人口总和
        long sum = porInfo.getProNum() + porInfo.getSoldierNum() + porInfo.getWoodcutterNum() + porInfo.getMinerNum();
        porInfo.setSum(sum);
    }

    @Override
    public void initCity(String accountCode, String groupCode, List<WarMap> list) {
        //初始化城池
        CityVo cityVo = new CityVo(accountCode, groupCode);
        //随机主城
        double index = Math.random() * list.size();
        WarMap warMap = list.get((int)index);

        //初始化主城
        warMap.setAccountCode(accountCode);
        WarMap.initWarMap(warMap);
        cityVo.setWarMap(warMap);
        cityVo.setWarId(warMap.getId());

        cityMapper.initCity(cityVo);
        warMapMapper.updateById(warMap);
        //初始化完成
    }

    @Override
    public void updateCityInfo(CityVo cityVo, boolean flag) {
        populationMapper.updateById(cityVo.getPorInfo());
        cityMapper.updateInfo(cityVo);
        if (flag) {
            warMapMapper.updateById(cityVo.getWarMap());
        }
    }

    @Override
    public String updateByRecruit(GroupMsg groupMsg, Integer num, String type, WarMap warMap) {
        String result;
        GroupAccountInfo accountInfo = groupMsg.getAccountInfo();
        String accountCode = accountInfo.getAccountCode();
        String accountNickname = accountInfo.getAccountNickname();

        CityVo cityVo = cityMapper.getCityInfo(accountCode, groupMsg.getGroupInfo().getGroupCode());

        if(warMap != null){
            //当前农民数量
            Integer proNum = warMap.getFarmerNum();
            int pro = proNum - num;
            int newNum = 0;
            if (pro >= 0){
                //表示当前人口数量够用
                FoodStore foodStore = cityVo.getFoodStore();
                WoodStore woodStore = cityVo.getWoodStore();
                MineStore mineStore = cityVo.getMineStore();
                /*
                 * 消耗资源
                 * 算出所招募数量需要的资源
                 */
                Map<String, Integer> map = CommonsUtils.recruitConsume(num, type);
                //判断资源是否够用
                if ( map !=null && map.get(Constants.FOOD) <= foodStore.getNum() &&
                        map.get(Constants.WOOD) <= woodStore.getNum() &&
                        map.get(Constants.MINE) <= mineStore.getNum()){
                    //资源更新
                    foodStore.setNum(foodStore.getNum() - map.get(Constants.FOOD));
                    woodStore.setNum(woodStore.getNum() - map.get(Constants.WOOD));
                    mineStore.setNum(mineStore.getNum() - map.get(Constants.MINE));

                    //资源够用则进行人员变更操作
                    warMap.setFarmerNum(pro);
                    switch (type) {
                        case Constants.SOLDIER:
                            newNum = warMap.getSoldierNum() + num;
                            warMap.setSoldierNum(newNum);
                            break;
                        case Constants.WOODCUTTER:
                            newNum = warMap.getWoodNum() + num;
                            warMap.setWoodNum(newNum);
                            break;
                        case Constants.MINER:
                            newNum = warMap.getMinerNum() + num;
                            warMap.setMinerNum(newNum);
                            break;
                        default: break;
                    }
                    warMapMapper.updateById(warMap);
                    this.updateCityInfo(cityVo, false);
                    //进行播报
                    result = MsgResult.recruitSuccess(accountNickname, type, newNum, cityVo, map, warMap);
                }else{
                    //资源不足，播报
                    result = MsgResult.notResources(accountNickname, Constants.RECRUIT);
                }
            }else {
                //人口不足，播报
                result = MsgResult.proNotNum(accountNickname, Long.valueOf(proNum));
            }
        }else{
            //未建立城邦
            result =  MsgResult.NOT_CITY;
        }

        return result;
    }

    @Override
    public String updateByDisband(GroupMsg groupMsg, Integer num, String type, WarMap warMap) {
        String result = "";
        GroupAccountInfo accountInfo = groupMsg.getAccountInfo();
        String accountCode = accountInfo.getAccountCode();
        String accountNickname = accountInfo.getAccountNickname();

        CityVo cityVo = cityMapper.getCityInfo(accountCode, groupMsg.getGroupInfo().getGroupCode());
        FoodStore foodStore = cityVo.getFoodStore();

        if(foodStore.getNum() >= num){
            //当前农民数量
            if (Constants.SOLDIER.equals(type)){
                Integer soldierNum = warMap.getSoldierNum();
                result =  this.disband(warMap, soldierNum, num, accountNickname, type);
            }else if (Constants.WOODCUTTER.equals(type)){
                Integer woodcutterNum = warMap.getWoodNum();
                result =  this.disband(warMap, woodcutterNum, num, accountNickname, type);
            }else if (Constants.MINER.equals(type)){
                Integer minerNum = warMap.getMinerNum();
                result =  this.disband(warMap, minerNum, num, accountNickname, type);
            }

            foodStore.setNum(foodStore.getNum() - num);
            result += "\n遣散费：" + num + "/剩余粮食：" + foodStore.getNum();
        }else{
            //粮食不够遣散费
            result =  MsgResult.notResources(accountNickname, type);
        }
        return result;
    }

    public String disband(WarMap warMap, Integer proNum, Integer disbandNum, String accountNickname, String type){
        int soldier = proNum - disbandNum;
        if (soldier >=0){
            //遣散成功，遣散的人员num成为农民
            warMap.setFarmerNum(warMap.getFarmerNum()+ disbandNum);
            warMap.setSoldierNum(soldier);
            //遣散成功
            warMapMapper.updateById(warMap);
            return MsgResult.disbandSuccess(accountNickname, type, soldier, warMap);
        }else {
            //遣散失败
            return MsgResult.disband(accountNickname, type, proNum);
        }
    }

    /**
     * 根据当前人员分布刷新每个玩家的资源
     */
    @Override
    public Map<String, List<String>> refresh() {
        Map<String, List<String>> map = new HashMap<>();
        List<City> cities = cityMapper.selectList(new QueryWrapper<>());
        for (City city :cities){
            String accountCode = city.getAccountCode();
            String groupCode = city.getGroupCode();
            CityVo cityInfo = this.getCityInfo(accountCode, groupCode);

            Population population = cityInfo.getPorInfo();
            //总人口
            Long sum = population.getSum();
            //农民人口
            Long proNum = population.getProNum();
            //伐木工数量
            Long woodcutterNum = population.getWoodcutterNum();
            // 矿工数量
            Long minerProNum = population.getMinerNum();

            //更新资源
            /*
             * 更新粮食
             */
            FoodStore foodStore = cityInfo.getFoodStore();
            //食物更新公式： 现有食物总量 + 农民数量 * 3 - 总人口
            Long foodMax = foodStore.getMax();
            Long num = foodStore.getNum();
            long newFoodNum = num + proNum * 3 - sum;
            if (newFoodNum < 0){
                //库存加生产小于消耗，粮食不够！
                //当前档期无法生产，全民罢工
                List<String> accountList = map.get(groupCode);
                if (accountList == null || accountList.size() == 0){
                    accountList = new ArrayList<>();
                }
                accountList.add(accountCode);
                map.put(groupCode, accountList);
            }else {
                //生产+消耗后的粮食总量大于等于0则可以进行之后的操作
                if (newFoodNum <= foodMax){
                    foodStore.setNum(newFoodNum);
                }else{
                    foodStore.setNum(foodMax);
                }
                /*
                 * 更新木材
                 */
                WoodStore woodStore = cityInfo.getWoodStore();
                Long woodMax = woodStore.getMax();
                Long woodNum = woodStore.getNum();
                //木材公式 库存 + 伐木工数量 * 2
                long newWoodNum = woodNum + woodcutterNum * 2;
                if (newWoodNum <= woodMax){
                    woodStore.setNum(newWoodNum);
                }else {
                    woodStore.setNum(woodMax);
                }
                /*
                 * 更新矿石
                 */
                MineStore mineStore = cityInfo.getMineStore();
                Long mineMax = mineStore.getMax();
                Long mineNum = mineStore.getNum();
                long newMineNum = mineNum + (minerProNum * 2);
                if (newMineNum <= mineMax){
                    mineStore.setNum(newMineNum);
                }else {
                    mineStore.setNum(mineMax);
                }
                //更新信息
                this.updateCityInfo(cityInfo, false);
            }
        }
        /*
         * 通知玩家粮食不够
         */
        return map;
    }

    @Override
    @Transactional
    public boolean capture(String accountCode, String groupCode, WarMap warMap, int num) {
        boolean flag;
        /*
        判断是否能占领
        获取该地区士兵数量，对比派遣的数量
         */
        Integer soldierNum = warMap.getSoldierNum();
        flag = num > soldierNum;
        if (flag) {
            //更新被占领者状态
            if (warMap.getAccountCode() != null) {
                overcomeOrDefeat(warMap.getAccountCode(), warMap.getGroupCode(), false);
            }
            //更新地图所属权
            warMap.setAccountCode(accountCode);
            warMap.setGroupCode(groupCode);
            warMap.setSoldierNum(num - soldierNum);
            // 成功占领，更新账号资源信息
            overcomeOrDefeat(accountCode, groupCode, true);
        }else{
            warMap.setSoldierNum(soldierNum - num);
        }
        warMapMapper.updateById(warMap);
        //返回占领状态
        return flag;
    }

    /**
     * 更新被占领者状态
     */
    public void overcomeOrDefeat(String accountCode, String groupCode, boolean overcomeOrDefeat) {
        CityVo cityVo = cityMapper.getCityInfo(accountCode, groupCode);
        FoodStore foodStore = cityVo.getFoodStore();
        WoodStore woodStore = cityVo.getWoodStore();
        MineStore mineStore = cityVo.getMineStore();

        if (overcomeOrDefeat) {
            //更新占领者城市数量
            cityVo.setNum(cityVo.getNum() + 1);
            //粮食上限增加
            foodStore.setMax(foodStore.getMax() + 600);
            //木材增加
            woodStore.setMax(woodStore.getMax() + 600);
            //矿石增加
            mineStore.setMax(mineStore.getMax() + 600);
        } else {
            //更新被占领者城市数量
            cityVo.setNum(cityVo.getNum() - 1);
            //粮食上限减少
            foodStore.setMax(foodStore.getMax() - 600);
            //木材上限减少
            woodStore.setMax(woodStore.getMax() - 600);
            //矿石上限减少
            mineStore.setMax(mineStore.getMax() - 600);
        }

        this.updateCityInfo(cityVo, false);
    }
}
